ποΈGitΠ―ΡΠ°ποΈ
Node / meshtastic / Meshtastic-Android / files / specs / 20260507-161758-node-list-layout / data-model.md
specs/20260507-161758-node-list-layout/data-model.md bd2863243bab6eb213401d949839a2bc74dde7e2 (bd286324) Text, 4.60 KB
Data Model β Node List Layout
Overview
The Node List Layout feature does not introduce new database entities. It adds preference keys to DataStore and a density enum that controls how existing T383838Node model data is rendered. The data model is entirely read-only from the layout perspective β node data comes from the existing Room KMP pipeline.
Entity Relationship
T282828
erDiagram
DataStore ||--o{ NodeListLayoutPreferences : stores
NodeListLayoutPreferences ||--|| NodeListDensity : selects
NodeListDensity ||--|| NodeItem : "renders (COMPLETE)"
NodeListDensity ||--|| NodeItemCompact : "renders (COMPACT)"
NodeItemCompact ||--o{ CompactToggle : "visibility driven by"
NodeItem }o--|| Node : reads
NodeItemCompact }o--|| Node : reads
Node ||--|| NodeEntity : "backed by"
Density Enum
T282828
Tff7b72package T7ee787org.meshtastic.feature.node.model
Tff7b72enum Tff7b72class T56d364NodeListDensity Tb4b4b4{
Te6edf3COMPLETETb4b4b4,
Te6edf3COMPACTTb4b4b4;
Tb4b4b4}
β’ Persisted as a T383838String (enum name) in DataStore under key T383838nodeListDensity.
β’ Default: T383838COMPLETE.
Preference Keys
T282828
Tff7b72package T7ee787org.meshtastic.core.prefs.ui
Tff7b72enum Tff7b72class T56d364NodeListLayoutPreferencesTb4b4b4(Tff7b72val Te6edf3keyTb4b4b4: Tffa657StringTb4b4b4, Tff7b72val Te6edf3defaultValueTb4b4b4: Tffa657BooleanTb4b4b4) Tb4b4b4{
Te6edf3SHOW_POWERTb4b4b4(Ta5d6ff"Ta5d6ffshouldShowPowerTa5d6ff"Tb4b4b4, Tff7b72trueTb4b4b4)Tb4b4b4,
Te6edf3SHOW_LAST_HEARDTb4b4b4(Ta5d6ff"Ta5d6ffshouldShowLastHeardTa5d6ff"Tb4b4b4, Tff7b72trueTb4b4b4)Tb4b4b4,
Te6edf3LAST_HEARD_RELATIVETb4b4b4(Ta5d6ff"Ta5d6fflastHeardIsRelativeTa5d6ff"Tb4b4b4, Tff7b72falseTb4b4b4)Tb4b4b4,
Te6edf3SHOW_LOCATIONTb4b4b4(Ta5d6ff"Ta5d6ffshouldShowLocationTa5d6ff"Tb4b4b4, Tff7b72trueTb4b4b4)Tb4b4b4,
Te6edf3SHOW_HOPSTb4b4b4(Ta5d6ff"Ta5d6ffshouldShowHopsTa5d6ff"Tb4b4b4, Tff7b72trueTb4b4b4)Tb4b4b4,
Te6edf3SHOW_SIGNALTb4b4b4(Ta5d6ff"Ta5d6ffshouldShowSignalTa5d6ff"Tb4b4b4, Tff7b72trueTb4b4b4)Tb4b4b4,
Te6edf3SHOW_CHANNELTb4b4b4(Ta5d6ff"Ta5d6ffshouldShowChannelTa5d6ff"Tb4b4b4, Tff7b72trueTb4b4b4)Tb4b4b4,
Te6edf3SHOW_ROLETb4b4b4(Ta5d6ff"Ta5d6ffshouldShowRoleTa5d6ff"Tb4b4b4, Tff7b72trueTb4b4b4)Tb4b4b4,
Te6edf3SHOW_TELEMETRYTb4b4b4(Ta5d6ff"Ta5d6ffshouldShowTelemetryTa5d6ff"Tb4b4b4, Tff7b72trueTb4b4b4)Tb4b4b4;
Tb4b4b4}
Preference Access Pattern
Each key is exposed as a T383838StateFlow<Boolean> in T383838UiPrefsImpl:
T282828
Tff7b72val Te6edf3shouldShowPowerTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657BooleanTff7b72> Tff7b72= Te6edf3dataStoreTb4b4b4.Te6edf3data
Tb4b4b4.Te6edf3map Tb4b4b4{ Tffa657itTff7b72[Te6edf3booleanPreferencesKeyTb4b4b4(Ta5d6ff"Ta5d6ffshouldShowPowerTa5d6ff"Tb4b4b4)Tff7b72] Tff7b72?: Tff7b72true Tb4b4b4}
Tb4b4b4.Te6edf3stateInTb4b4b4(Te6edf3scopeTb4b4b4, Te6edf3SharingStartedTb4b4b4.Te6edf3EagerlyTb4b4b4, Tff7b72trueTb4b4b4)
The density preference follows the same pattern but maps to the enum:
T282828
Tff7b72val Te6edf3nodeListDensityTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3NodeListDensityTff7b72> Tff7b72= Te6edf3dataStoreTb4b4b4.Te6edf3data
Tb4b4b4.Te6edf3map Tb4b4b4{ Te6edf3prefs Tff7b72-Tff7b72>
Tff7b72val Te6edf3name Tff7b72= Te6edf3prefsTff7b72[Te6edf3stringPreferencesKeyTb4b4b4(Ta5d6ff"Ta5d6ffnodeListDensityTa5d6ff"Tb4b4b4)Tff7b72] Tff7b72?: Ta5d6ff"Ta5d6ffCOMPLETETa5d6ff"
Te6edf3NodeListDensityTb4b4b4.Te6edf3valueOfTb4b4b4(Te6edf3nameTb4b4b4)
Tb4b4b4}
Tb4b4b4.Te6edf3stateInTb4b4b4(Te6edf3scopeTb4b4b4, Te6edf3SharingStartedTb4b4b4.Te6edf3EagerlyTb4b4b4, Te6edf3NodeListDensityTb4b4b4.Te6edf3COMPLETETb4b4b4)
Node Data Fields Used by Layout
The layout reads from the existing T383838Node model in T383838core:model. No new fields are added.
βββββββββββββββββββββββββ¬βββββββββββββ¬ββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Field β Type β Used By β Condition β
βββββββββββββββββββββββββΌβββββββββββββΌββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β T383838longName β T383838String? β Both β Always shown β
β T383838shortName β T383838String? β Both β NodeChip avatar β
β T383838lastHeard β T383838Long β Both β Non-zero, not > 1 year future β
β T383838hopsAway β T383838Int β Both β T383838> 0 for hop count, T383838== 0 for signal β
β T383838snr β T383838Float β Both β T383838!= 0 and T383838!viaMqtt β
β T383838rssi β T383838Int β Both β Signal quality via T383838determineSignalQuality(snr, rβ¦ β
β T383838batteryLevel β T383838Int? β Both β Non-null β
β T383838channel β T383838Int β Both β T383838> 0 β
β T383838position β T383838Position? β Both β Non-null, valid lat/lon β
β T383838role β T383838DeviceRole β Both β Always (defaults to 0) β
β T383838viaMqtt β T383838Boolean β Both β Signal exclusion gate β
β T383838isFavorite β T383838Boolean β Both β Star icon β
β T383838hasPositionLog β T383838Boolean β Both β Log icon visibility β
β T383838hasEnvironmentLog β T383838Boolean β Both β Log icon visibility β
β T383838hasDetectionSensorLog β T383838Boolean β Both β Log icon visibility β
β T383838hasTracerouteLog β T383838Boolean β Both β Log icon visibility β
β T383838hasDeviceMetricsLog β T383838Boolean β Both β Log icon visibility β
βββββββββββββββββββββββββ΄βββββββββββββ΄ββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββββββ
Adaptive Chip Sizing
The compact T383838NodeChip size is derived from a T383838lineCount property:
T282828
Tff7b72val Te6edf3lineCountTb4b4b4: Tffa657Int Tff7b72= Te6edf3buildList Tb4b4b4{
Te6edf3addTb4b4b4(T79c0ff1Tb4b4b4) T8b949e// Row 1: name β always present
Tff7b72if Tb4b4b4(Te6edf3shouldShowLastHeardTb4b4b4) Te6edf3addTb4b4b4(T79c0ff1Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3shouldShowLocation Tff7b72|Tff7b72| Te6edf3shouldShowHops Tff7b72|Tff7b72| Te6edf3shouldShowSignal Tff7b72|Tff7b72|
Te6edf3shouldShowChannel Tff7b72|Tff7b72| Te6edf3shouldShowRole Tff7b72|Tff7b72| Te6edf3shouldShowTelemetryTb4b4b4) Te6edf3addTb4b4b4(T79c0ff1Tb4b4b4)
Tb4b4b4}Tb4b4b4.Te6edf3size
Tff7b72val Te6edf3chipSizeTb4b4b4: Te6edf3Dp Tff7b72= Te6edf3maxTb4b4b4(T79c0ff3T79c0ff6.Te6edf3dpTb4b4b4, Te6edf3minTb4b4b4(T79c0ff7T79c0ff0.Te6edf3dpTb4b4b4, T79c0ff2T79c0ff4.Te6edf3dp Tff7b72* Te6edf3lineCountTb4b4b4)Tb4b4b4)
βββββββββββββ¬ββββββββββββ¬βββββββββββββββββββββββββββββββββββββββ
β lineCount β Chip Size β Active Rows β
βββββββββββββΌββββββββββββΌβββββββββββββββββββββββββββββββββββββββ€
β 1 β 36.dp β Name only β
β 2 β 48.dp β Name + last heard OR Name + combined β
β 3 β 70.dp β Name + last heard + combined β
βββββββββββββ΄ββββββββββββ΄βββββββββββββββββββββββββββββββββββββββ
Validation Rules
β’ T383838nodeListDensity must be a valid T383838NodeListDensity enum name. Invalid values fall back to T383838COMPLETE.
β’ T383838lastHeardIsRelative is functionally irrelevant when T383838shouldShowLastHeard is T383838false (the UI disables the toggle).
β’ All boolean preferences default to T383838true except T383838lastHeardIsRelative which defaults to T383838false.
β’ The layout never writes to T383838Node data β all mutations flow through the existing packet processing pipeline.
Served by rngit 1.5.0 - Generated in 0.07s